/**
 * 表格编辑实例存储
 * @type {Map<String, EditorStore>}
 */
import Vue from 'vue'
import merge from 'merge'

class EditorStore {
  constructor(tableInstance) {
    this.table = tableInstance
    /**
     * 记录行数据的编辑状态
     * 当 value 值为 true时，表示整行处于编辑状态
     * 否则其值应当为数组，其每一项为正在编辑的列名称
     * @type {{key: String, value: any}}
     */
    this.editState = Object.create({})
    /**
     * 数据变更状态
     * @type {{[rowId: String]: {data: {}, state: string}}}
     */
    this.changeStage = Object.create({})
  }

  getRowId(row) {
    return this.table.getRowId(row)
  }

  beginEditRow(row) {
    Vue.set(this.editState, this.getRowId(row), true)
  }

  endEditRow(row) {
    Vue.delete(this.editState, this.getRowId(row))
  }

  cancelEditRow(row) {
    const rowId = this.getRowId(row)
    Vue.delete(this.changeStage, rowId)
    Vue.delete(this.editState, rowId)
  }

  beginEditCell(row, field) {
    const rowId = this.getRowId(row)
    // 已经全行编辑了，忽略此操作
    if (this.editState[rowId] === true) {
      return
    }
    const fields = this.editState[rowId] || []
    if (fields.indexOf(field) !== -1) {
      return
    }
    fields.push(field)
    Vue.set(this.editState, rowId, merge.clone(fields))
  }

  endEditCell(row, field) {
    const rowId = this.getRowId(row)
    // 已经全行编辑了，忽略此操作
    if (this.editState[rowId] === true) {
      return
    }
    const fields = this.editState[rowId]
    const idx = fields.indexOf(field)
    if (idx === -1) {
      return
    }
    fields.splice(idx, 1)
    if (Object.keys(fields).length) {
      Vue.set(this.editState, rowId, fields)
    } else {
      Vue.delete(this.editState, rowId)
    }
  }

  cancelEditCell(row, field) {
    const rowId = this.getRowId(row)
    // 已经全行编辑了，忽略此操作
    const editingFields = this.editState[rowId]
    if (!editingFields) {
      return
    }
    if (editingFields === true) {
      return
    }
    const idx = editingFields.indexOf(field)
    if (idx === -1) {
      return
    }
    const changes = this.getChanges(row)
    if (changes && changes.hasOwnProperty(rowId)) {
      if (changes[rowId].hasOwnProperty(field)) {
        Vue.delete(changes[rowId], field)
      }
    }
    editingFields.splice(idx, 1)
    if (editingFields.length) {
      Vue.set(this.editState, rowId, editingFields)
    } else {
      Vue.delete(this.editState, rowId)
    }
  }

  setChange(row, field, value) {
    const rowId = this.getRowId(row)
    const changes = this.getChanges(row) || {}
    if (changes[field] === row[field]) {
      Vue.delete(changes, field)
    } else {
      Vue.set(changes, field, value)
    }
    Vue.set(this.changeStage, rowId, changes)
  }

  updateChanges() {

  }

  cancelChanges() {

  }

  getChanges(row) {
    if (row) {
      return merge.clone(this.changeStage[this.getRowId(row)])
    }
    return merge.clone(this.changeStage)
  }

  getEditingRows() {
  }

  isRowEditing(row) {
    return !!this.editState[this.getRowId(row)]
  }

  isCellEditing(row, field) {
    const editingFields = this.editState[this.getRowId(row)]
    if (!editingFields) {
      return false
    }
    // 整行编辑中
    if (editingFields === true) {
      return true
    }
    return editingFields.indexOf(field) !== -1
  }

  isCellChanged(row, field) {
    const changes = this.getChanges(row)
    if (!changes) {
      return false
    }
    return changes.hasOwnProperty(field)
  }

  getCellValue(row, field) {
    const changes = this.getChanges(row)
    if (!changes) {
      return row[field]
    }
    return changes.hasOwnProperty(field) ? changes[field] : row[field]
  }
}

export default EditorStore
